跳到主要内容

设计模式

异常处理 方法

package com.whalefall.learncases.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;

/**
* @author WhaleFall
* @create 2022-05-28 10:41
* codes copy from => https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
*/
@Slf4j
@ControllerAdvice// 指定为全局异常处理
public class ExceptionHandlingController {

// Specify name of a specific view that will be used to display the error:
@ExceptionHandler(SQLException.class)
public String databaseError() {
// Nothing to do. Returns the logical view name of an error page, passed
// to the view-resolver(s) in usual way.
// Note that the exception is NOT available to this view (it is not added
// to the model) but see "Extending ExceptionHandlerExceptionResolver"
// below.
return "databaseError";
}

// Total control - setup a model and return the view name yourself. Or
// consider subclassing ExceptionHandlerExceptionResolver (see below).
@ExceptionHandler(Exception.class)
public ModelAndView handleError(HttpServletRequest req, Exception ex) {
log.error("Request: " + req.getRequestURL() + " raised " + ex);

ModelAndView mav = new ModelAndView();
mav.addObject("exception", ex);
mav.addObject("url", req.getRequestURL());
mav.setViewName("error");
return mav;
}

}

基于接口设计

  1. 接口类
package com.whalefall.learncases.design;

/**
* @author WhaleFall
* @create 2022-07-25 19:21
*/
public interface IService {
boolean doService();

boolean doServiceBefore();

boolean doServiceAfter();

void doLog();
}

  1. 接口实现类
package com.whalefall.learncases.design;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
* @author WhaleFall
* @create 2022-07-24 6:34
*/
@Slf4j
@Component
public class AService implements IService {
@Override
public boolean doService() {
log.info("do A service");
if (true)
throw new RuntimeException("Exception msg1");
return true;
}

@Override
public boolean doServiceBefore() {
return false;
}

@Override
public boolean doServiceAfter() {
return false;
}

@Override
public void doLog() {
if (true)
throw new RuntimeException("Exception msg2");
log.error("A1 do log");
}
}
  1. 核心流程封装

可以使用单例设计模式

  • 方法1单例设计模式
package com.whalefall.learncases.design;

import lombok.extern.slf4j.Slf4j;

import javax.validation.constraints.NotNull;
import java.util.function.Consumer;

/**
* @author WhaleFall
* @create 2022-07-24 6:26
*/
@Slf4j
public class SProcessService {
private SProcessService() {

}

private static class SProcessServiceHolder {
private static final SProcessService INSTANCE = new SProcessService();
}

public static SProcessService getInstance() {
return SProcessServiceHolder.INSTANCE;
}

public boolean handle(IService service, Consumer<Exception> exceptionConsumer) {
serviceBefore(service);
service(service, exceptionConsumer);
serviceAfter(service);
log(service, exceptionConsumer);
return true;
}

private void serviceAfter(@NotNull IService service) {
service.doServiceAfter();
}

private void serviceBefore(@NotNull IService service) {
service.doServiceBefore();
}

private void service(@NotNull IService service, Consumer<Exception> exceptionConsumer) {
try {
service.doService();
} catch (Exception e1) {
exceptionConsumer.accept(e1);
throw e1;
}
}

private void log(@NotNull IService service, Consumer<Exception> exceptionConsumer) {
try {
service.doLog();
} catch (Exception e2) {
log.error("failed do log");
exceptionConsumer.accept(e2);
}
}
}

  • 方法2 注入容器中
package com.whalefall.learncases.design;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import java.util.function.Consumer;

/**
* @author WhaleFall
* @create 2022-07-24 6:26
*/
@Component
@Slf4j
public class ProcessService {

public boolean handle(IService service, Consumer<Exception> exceptionConsumer) {
serviceBefore(service);
service(service, exceptionConsumer);
serviceAfter(service);
log(service, exceptionConsumer);
return true;
}

private void serviceAfter(@NotNull IService service) {
service.doServiceAfter();
}

private void serviceBefore(@NotNull IService service) {
service.doServiceBefore();
}

private void service(@NotNull IService service, Consumer<Exception> exceptionConsumer) {
try {
service.doService();
} catch (Exception e1) {
exceptionConsumer.accept(e1);
throw e1;
}
}

private void log(@NotNull IService service, Consumer<Exception> exceptionConsumer) {
try {
service.doLog();
} catch (Exception e2) {
log.error("failed do log");
exceptionConsumer.accept(e2);
}
}
}


  1. 调用案例

package com.whalefall.learncases.design;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @author WhaleFall
* @create 2022-07-24 6:37
*/
@RestController
@Slf4j
public class ControllerA {

private IService service;

private ProcessService processService;

public ControllerA(IService service, ProcessService processService) {
this.service = service;
this.processService = processService;
}

@GetMapping("/testA")
public boolean getA(){
return processService.handle(service, e -> log.error(e.getMessage(), e));
}
}

完整代码

DDD

实体对象不能直接赋值,领域对象不能直接new出来,应该使用工厂方法,建造者模式来实现。

协议
  • 本作品代码部分采用 Apache 2.0协议进行许可。遵循许可的前提下,你可以自由地对代码进行修改,再发布,可以将代码用作商业用途。但要求你:

    • 署名:在原有代码和衍生代码中,保留原作者署名及代码来源信息。
    • 保留许可证:在原有代码和衍生代码中,保留Apache 2.0协议文件。
  • 本作品文档部分采用知识共享署名 4.0 国际许可协议进行许可。 遵循许可的前提下,你可以自由地共享,包括在任何媒介上以任何形式复制、发行本作品,亦可以自由地演绎、修改、转换或以本作品为基础进行二次创作。但要求你:

    • 署名:应在使用本文档的全部或部分内容时候,注明原作者及来源信息。
    • 非商业性使用:不得用于商业出版或其他任何带有商业性质的行为。如需商业使用,请联系作者。
    • 相同方式共享的条件:在本文档基础上演绎、修改的作品,应当继续以知识共享署名 4.0国际许可协议进行许可。